package org.jslaughter.level;

import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.nvframe.component.state.Position;
import org.nvframe.entity.Entity;
import org.nvframe.exception.NVFrameException;
import org.nvframe.factory.EntityFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

public class Level {

	public void createFromXML(InputStream is) throws NVFrameException {
		DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
		DocumentBuilder docBuilder = null;
		
		try {
			docBuilder = docBuilderFactory.newDocumentBuilder();
		} catch (ParserConfigurationException e) {
			throw new NVFrameException("Could not load entities xmlfile", e);
		}
		
		Document doc = null;
		
		try {
			doc = docBuilder.parse(is);
		} catch (SAXException e) {
			throw new NVFrameException("Could not load entities xmlfile", e);
		} catch (IOException e) {
			throw new NVFrameException("Could not load entities xmlfile", e);
		}

		doc.getDocumentElement().normalize();

		NodeList listEntities = doc.getElementsByTagName("layout");
		int totalEntities = listEntities.getLength();

		for (int entity_id = 0; entity_id < totalEntities; entity_id++) {

			Node entityNode = listEntities.item(entity_id);

			if (entityNode.getNodeType() == Node.ELEMENT_NODE) {
				Element entityEl = (Element) entityNode;
				String layoutId = entityEl.getAttribute("id");
				String entityId = entityEl.getAttribute("entityId");

				// create a map with entitysettings
				Map<String, String> settings = buildSettingsMap(entityEl);

				buildLayout(layoutId, entityId, settings);
			}
		}
	}
	
	/**
	 * 
	 * @param layoutId
	 * @param settings
	 * @throws NVFrameException 
	 */
	private void buildLayout(String layoutId, String entityId, Map<String, String> settings) throws NVFrameException {
		Entity entity = EntityFactory.getInstance().getEntityFromPrototype(entityId);
		
		// set position
		if(settings.containsKey("x") && settings.containsKey("y")) {
			Position position = (Position) entity.getComponent(Position.class);
			
			if(position == null)
				throw new NVFrameException("cannot set initial position, entity: " + entityId);
			else {
				float x = Integer.parseInt(settings.get("x"));
				float y = Integer.parseInt(settings.get("y"));
				
				position.setXY(x, y);
			}
		}
	}

	/**
	 * Creates a map with the layout settings
	 * 
	 * @param parentEl
	 * @return HashMap<String, String> with layout settings
	 */
	private static HashMap<String, String> buildSettingsMap(Element parentEl) {
		HashMap<String, String> map = new HashMap<String, String>();
		
		if(parentEl.getElementsByTagName("settings") == null)
			return map;
		
		NodeList layoutSettings = (NodeList) parentEl.getElementsByTagName("settings").item(0);
		
		if(layoutSettings == null)
			return map;
		
		NodeList layoutSetting = ((Element) layoutSettings).getElementsByTagName("setting");
		
		for(int setting_id = 0; setting_id < layoutSetting.getLength(); setting_id++) {

			Node settingNode = layoutSetting.item(setting_id);
			
			if (settingNode.getNodeType() == Node.ELEMENT_NODE) {
				Element settingEl = (Element) settingNode;
				map.put(settingEl.getAttribute("id"), settingEl.getTextContent().trim());
			}
		}
		
		return map;
	}
	
}
